#pragma once

#include <exception>
#include <string>
#include <type_traits>
#include <typeinfo>
#include <utility>
#include <variant>

#if defined(__has_cpp_attribute)
#if __has_cpp_attribute(no_unique_address)
#define KP_NO_UNIQUE_ADDRESS [[no_unique_address]]
#else
#define KP_NO_UNIQUE_ADDRESS
#endif
#else
#define KP_NO_UNIQUE_ADDRESS
#endif

#if defined(__cpp_lib_expected) && (__cpp_lib_expected >= 202211L)
#define KP_HAS_STD_EXPECTED
#endif

#ifndef KP_HAS_STD_EXPECTED

/**
 * @file expected.h
 * @brief 为 C++17 环境提供与 C++23 std::expected 兼容的轻量级实现。
 *
 * 本文件在检测到编译器尚未支持 <expected> 时，启用自定义的 kp::expected 模板。
 * 设计目标：
 * 1. 接口与 std::expected 保持高度一致，方便未来无缝迁移。
 * 2. 零额外运行时开销：内部使用 std::variant 实现，大小等于 max(sizeof(T), sizeof(E)) + 判别式。
 * 3. 异常安全：所有可能抛异常的接口均提供强异常保证或基础异常保证。
 * 4. 可组合性：提供 and_then / transform / transform_error / or_else 等 monadic 操作，
 *    使错误处理链式调用成为可能，避免深层嵌套。
 * 5. 可空性：expected<void,E> 特化支持“仅关心成败”的场景。
 */

namespace kp
{

/**
 * @brief 前向声明 kp::expected 主模板。
 * @tparam T 期望承载的“成功”值类型
 * @tparam E 错误类型，通常推荐为 std::error_code、std::string 或自定义错误枚举
 */
template <class T, class E>
class expected;

/**
 * @brief 类型萃取：判断类型是否实例化自 kp::expected 模板。
 * @details 用于 SFINAE 约束，确保 monadic 操作链中返回类型必须是 expected<U,E>，
 *          防止用户误传普通可选类型。
 */
template <class>
struct is_expected_template : std::false_type
{
};
template <class U, class Err>
struct is_expected_template<expected<U, Err>> : std::true_type
{
};

/**
 * @brief 类型萃取：判断 Ret 是否为 kp::expected<X,Err> 且 Err 与当前实例相同。
 * @details 在 and_then / or_else 中用于校验“错误类型”必须一致，
 *          避免跨错误域的静默转换，保证错误语义清晰。
 */
template <class Ret, class Err>
struct is_expected_with_error : std::false_type
{
};
template <class U, class Err>
struct is_expected_with_error<expected<U, Err>, Err> : std::true_type
{
};

/**
 * @brief 标签类型，用于 in-place 构造错误值。
 * @details 类似 std::in_place，但语义上强调“构造的是错误分支”，
 *          避免与值构造重载产生歧义。
 */
struct unexpect_t
{
    constexpr explicit unexpect_t() = default;
};
/**
 * @brief 内联 constexpr 实例，供用户以 kp::unexpected(kp::unexpect, args...) 方式调用。
 */
inline constexpr unexpect_t unexpect{};

/**
 * @brief 访问 expected 的 value() 但当前含错误时抛出的异常类型。
 * @details 继承自 std::exception，保证与 std::expected 的异常类型兼容。
 *          内部持有错误值副本，确保异常对象离开作用域后仍可取到错误信息。
 * @tparam E 错误类型，必须与 expected<T,E> 中的 E 完全一致
 */
template <class E>
class bad_expected_access : public std::exception
{
public:
    /**
     * @brief 从错误值构造异常对象。
     * @param e 将被移动存储的错误值；要求 E 满足 std::is_nothrow_move_constructible
     *          以提供强异常保证，防止构造异常本身再抛异常。
     * @note 在 Debug 模式下拼接类型名，方便调试；Release 模式仅返回固定字符串，
     *       避免 RTTI 开销。
     */
    explicit bad_expected_access(E e) noexcept(std::is_nothrow_move_constructible<E>::value)
        : e_(std::move(e))
    {
#ifndef NDEBUG
        what_.assign("bad_expected_access<");
        what_.append(typeid(E).name());
        what_.push_back('>');
#endif
    }

    /**
     * @brief 返回异常描述。
     * @return 在 Debug 下返回带模板参数名的字符串；Release 下返回固定字符串。
     */
    const char * what() const noexcept override
    {
#ifndef NDEBUG
        return what_.c_str();
#else
        return "bad_expected_access";
#endif
    }

    /*@{*/
    /**
     * @brief 取得内部错误值。
     * @details 提供 const / mutable / rvalue 三种重载，支持在 catch 块中
     *          以不同方式消费错误值。
     */
    E & error() & noexcept { return e_; }
    const E & error() const & noexcept { return e_; }
    E && error() && noexcept { return std::move(e_); }
    /*@}*/

private:
    KP_NO_UNIQUE_ADDRESS E e_; ///< 错误值，使用 [[no_unique_address]] 优化空基类
#ifndef NDEBUG
    mutable std::string what_; ///< 仅 Debug 模式使用，延迟拼接
#endif
};

/**
 * @brief 用于包装“错误值”的轻量级容器，语义上与值无关。
 * @details 设计初衷：
 * 1. 与 expected<T,E> 的值构造区分，避免隐式转换带来的歧义。
 * 2. 提供与 std::unexpected<E> 一致的接口，方便未来迁移到标准库。
 * 3. 支持结构化绑定及比较操作，满足“错误值也是一等公民”的理念。
 * @tparam E 错误类型，要求可复制或可移动
 */
template <class E>
class unexpected_t
{
public:
    /**
     * @brief 从错误值构造。
     * @param e 将被移动存储的错误值
     * @note explicit 防止与 expected 的值构造产生冲突
     */
    constexpr explicit unexpected_t(E e) : err_(std::move(e)) {}

    /*@{*/
    /**
     * @brief 取得内部错误值。
     * @details 提供 const / mutable / rvalue 三种重载，方便调用者按需消费。
     */
    constexpr E & error() & { return err_; }
    constexpr const E & error() const & { return err_; }
    constexpr E && error() && { return std::move(err_); }
    /*@}*/

    /**
     * @brief 相等比较，基于 err_ 的 operator==。
     */
    friend constexpr bool operator==(const unexpected_t & a, const unexpected_t & b)
    {
        return a.err_ == b.err_;
    }
    friend constexpr bool operator!=(const unexpected_t & a, const unexpected_t & b)
    {
        return !(a == b);
    }

    /**
     * @brief 成员 swap，提供 noexcept 保证。
     */
    void swap(unexpected_t & other) noexcept(noexcept(std::swap(err_, other.err_)))
    {
        using std::swap;
        swap(err_, other.err_);
    }

private:
    E err_; ///< 实际存储的错误值
};

/**
 * @brief ADL 友好的自由函数 swap。
 */
template <class E>
inline void
swap(unexpected_t<E> & a, unexpected_t<E> & b) noexcept(noexcept(a.swap(b)))
{
    a.swap(b);
}

/**
 * @brief 工厂函数：从错误值构造 unexpected_t<E>。
 * @details 使用 std::move 避免不必要的拷贝，模板形参推导简化调用方代码。
 * @param e 错误值
 * @return unexpected_t<E> 临时对象，可直接用于构造 expected<T,E> 的错误分支
 */
template <class E>
constexpr unexpected_t<E>
unexpected(E e)
{
    return unexpected_t<E>(std::move(e));
}
/**
 * @brief C++17 环境下对 C++23 std::expected 的轻量级兼容实现（非 void 特化）。
 *
 * @tparam T 成功时承载的“值”类型，需满足可复制或移动构造。
 * @tparam E 错误类型，通常选用 std::error_code、std::string 或自定义枚举。
 *
 * @details
 * 设计初衷：
 * 1. 零开销抽象：内部以 std::variant<T, unexpected_t<E>> 存储，大小为
 * max(sizeof(T),sizeof(E))+判别式， 与手写 union
 * 方案等价，但自动获得编译器生成的构造/析构/拷贝/移动语义。
 * 2. 异常安全：所有可能抛异常的接口均提供强异常保证（如 value()）或基础保证（如 transform）。
 * 3. 可组合性：提供 and_then / transform / transform_error / or_else 等 monadic 操作，
 *    使错误处理可链式表达，避免深层 if-else 嵌套。
 * 4. 无缝迁移：当编译器支持 <expected> 时，通过宏一键切换至 std 实现，无需改动业务代码。
 * 5. 统一错误类型：强制要求 and_then / or_else 返回的 expected<U,E> 必须与当前实例共用相同的 E，
 *    避免跨错误域的静默转换，保证错误语义清晰。
 *
 * 使用示例：
 * @code
 * kp::expected<int, std::string> parse(std::string_view s) noexcept {
 *     if (s.empty()) return kp::unexpected("empty input");
 *     return std::stoi(std::string(s));
 * }
 *
 * auto r = parse("42")
 *              .and_then([](int v){ return kp::expected<double,std::string>(v*2.0); })
 *              .transform([](double v){ return std::to_string(v); });
 * if (r) std::cout << *r;   // "84"
 * @endcode
 */
template <class T, class E>
class [[nodiscard]] expected
{
    /**
     * @brief 内部存储类型。
     * @details
     * 0 号索引为 T，表示“成功”状态；<br>
     * 1 号索引为 unexpected_t<E>，表示“错误”状态。<br>
     * 借助 std::variant 的自动判别式与最大对齐特性，实现零额外空间开销。
     */
    using storage_t = std::variant<T, unexpected_t<E>>;

public:
    /*@{*/
    /**
     * @name 构造与赋值
     */
    /**
     * @brief 默认构造，仅当 T 可默认构造时启用。
     * @details
     * 提供与 std::expected 一致的默认语义：构造一个含值的成功状态。
     * 若 T 不可默认构造，则删除此重载，强制用户显式提供初始值或错误。
     * @note 异常规格：当 T 的默认构造为 noexcept 时，本构造函数亦为 noexcept。
     */
    template <class U = T, typename = std::enable_if_t<std::is_default_constructible<U>::value>>
    constexpr expected() noexcept(std::is_nothrow_default_constructible<T>::value) : st_(T{})
    {
    }

    /**
     * @brief 从 T 拷贝构造。
     * @details
     * 进入“成功”状态，拷贝语义与 std::variant 保持一致。
     * 若 T 的拷贝构造抛异常，则直接向上传播，此时 *this 尚未构造完成，无额外回滚责任。
     */
    constexpr expected(const T & v) : st_(v) {}

    /**
     * @brief 从 T 移动构造。
     * @details
     * 进入“成功”状态，当 T 的移动构造为 noexcept 时，整个操作为 noexcept。
     */
    constexpr expected(T && v) noexcept(std::is_nothrow_move_constructible<T>::value)
        : st_(std::move(v))
    {
    }

    /**
     * @brief 就地构造 T。
     * @details
     * 等价于 expected(std::in_place, args...)，避免额外的移动/拷贝。
     * 常用于构造代价较高或不可拷贝的类型。
     */
    template <class... Args>
    constexpr explicit expected(std::in_place_t, Args &&... args)
        : st_(std::in_place_index<0>, std::forward<Args>(args)...)
    {
    }

    /**
     * @brief 从 unexpected_t<E> 拷贝构造，进入“错误”状态。
     * @details
     * 该重载与 T 的构造形成重载决议，保证“错误”路径的显式性。
     */
    constexpr expected(const unexpected_t<E> & ue) : st_(ue) {}

    /**
     * @brief 从 unexpected_t<E> 移动构造。
     * @details
     * 当 E 的移动构造为 noexcept 时，整个操作为 noexcept。
     */
    constexpr expected(unexpected_t<E> && ue) noexcept(std::is_nothrow_move_constructible<E>::value)
        : st_(std::move(ue))
    {
    }

    /**
     * @brief 就地构造 E（错误值）。
     * @details
     * 使用 kp::unexpect 标签消除与值构造的歧义，语义清晰。
     * 内部通过 unexpected_t<E>(E(...)) 二次包装，确保与拷贝/移动重载的行为一致性。
     */
    template <class... Args>
    constexpr explicit expected(unexpect_t, Args &&... args)
        : st_(std::in_place_index<1>, unexpected_t<E>(E(std::forward<Args>(args)...)))
    {
    }
    /*@}*/

    /*@{*/
    /**
     * @name 状态查询
     */
    /**
     * @brief 查询是否处于“成功”状态。
     * @return 当且仅当内部持有 T 时返回 true。
     * @note noexcept 且 constexpr，可放心在核心路径使用。
     */
    constexpr bool has_value() const noexcept { return std::holds_alternative<T>(st_); }

    /**
     * @brief 布尔转换，等价于 has_value()。
     * @details
     * 显式转换避免与整数类型的隐式比较，但允许在 if / while 等语境中直接使用。
     */
    constexpr explicit operator bool() const noexcept { return has_value(); }
    /*@}*/

    /*@{*/
    /**
     * @name 值访问
     * @pre has_value() == true，否则抛出 bad_expected_access<E>。
     */
    /**
     * @brief 左值引用访问值。
     * @throw bad_expected_access<E> 若当前为错误状态。
     * @return 内部 T 的左值引用。
     */
    constexpr T & value() &
    {
        if (!has_value())
            throw bad_expected_access<E>(std::get<1>(st_).error());
        return std::get<0>(st_);
    }

    /**
     * @brief const 左值引用访问值。
     * @throw bad_expected_access<E> 若当前为错误状态。
     * @return 内部 T 的 const 左值引用。
     */
    constexpr const T & value() const &
    {
        if (!has_value())
            throw bad_expected_access<E>(std::get<1>(st_).error());
        return std::get<0>(st_);
    }

    /**
     * @brief 右值引用访问值。
     * @throw bad_expected_access<E> 若当前为错误状态。
     * @return 内部 T 的右值引用，支持移动语义。
     */
    constexpr T && value() &&
    {
        if (!has_value())
            throw bad_expected_access<E>(std::move(std::get<1>(st_)).error());
        return std::move(std::get<0>(st_));
    }

    /**
     * @brief 指针语义访问。
     * @details
     * 行为与 std::optional / std::expected 保持一致，返回指向内部 T 的指针。
     * 调用前若未检查 has_value() 且当前为错误状态，则 value() 会抛出异常，
     * 因此 operator-> 与 operator* 均基于 value() 实现，确保异常安全。
     */
    constexpr T * operator->() { return &value(); }
    constexpr const T * operator->() const { return &value(); }
    constexpr T & operator*() & { return value(); }
    constexpr const T & operator*() const & { return value(); }
    /*@}*/

    /*@{*/
    /**
     * @name 错误访问
     * @pre has_value() == false，否则行为未定义（与 std::expected 保持一致）。
     */
    /**
     * @brief 左值引用访问错误值。
     * @return 内部 unexpected_t<E> 所持有的 E 的左值引用。
     */
    constexpr E & error() & { return std::get<1>(st_).error(); }

    /**
     * @brief const 左值引用访问错误值。
     * @return 内部 unexpected_t<E> 所持有的 E 的 const 左值引用。
     */
    constexpr const E & error() const & { return std::get<1>(st_).error(); }

    /**
     * @brief 右值引用访问错误值。
     * @return 内部 unexpected_t<E> 所持有的 E 的右值引用，支持移动语义。
     */
    constexpr E && error() && { return std::move(std::get<1>(st_)).error(); }
    /*@}*/

    /*@{*/
    /**
     * @name 就地重新构造
     */
    /**
     * @brief 就地构造 T，覆盖当前状态（无论原状态是值还是错误）。
     * @details
     * 若当前已为值状态，则直接析原值并重新构造；若为错误状态，则先析构错误值再构造值。
     * 返回新构造值的引用，方便调用方继续操作。
     * @tparam Args 传递给 T 构造函数的形参包。
     * @return 新构造的 T 的左值引用。
     */
    template <class... Args>
    T & emplace(Args &&... args)
    {
        st_.template emplace<0>(std::forward<Args>(args)...);
        return std::get<0>(st_);
    }

    /**
     * @brief 就地构造 E，覆盖当前状态。
     * @details
     * 内部通过 unexpected_t<E>(E(...)) 包装，保证与构造函数的语义一致性。
     * @tparam Args 传递给 E 构造函数的形参包。
     * @return 新构造的 E 的左值引用。
     */
    template <class... Args>
    E & emplace_error(Args &&... args)
    {
        st_.template emplace<1>(unexpected_t<E>(E(std::forward<Args>(args)...)));
        return std::get<1>(st_).error();
    }
    /*@}*/

    /*@{*/
    /**
     * @name 默认值策略
     */
    /**
     * @brief 若处于成功状态则返回值，否则返回给定的默认值。
     * @details
     * 左值版本：当 *this 为成功时返回内部值的拷贝，否则将 u 转换为 T 返回。
     * 该接口与 std::optional::value_or 风格一致，用于快速提取值或回退。
     * @tparam U 可转换为 T 的类型，通常与 T 相同或可隐式转换。
     * @param u 默认值。
     * @return 成功时值，否则 static_cast<T>(u)。
     */
    template <class U>
    constexpr T value_or(U && u) const &
    {
        return has_value() ? std::get<0>(st_) : static_cast<T>(std::forward<U>(u));
    }

    /**
     * @brief 右值版本 value_or。
     * @details
     * 若 *this 为成功，则移动内部值返回；否则仍按 static_cast<T>(u) 处理。
     * 当 T 为移动构造优化类型时，可避免一次拷贝。
     */
    template <class U>
    constexpr T value_or(U && u) &&
    {
        return has_value() ? std::move(std::get<0>(st_)) : static_cast<T>(std::forward<U>(u));
    }

    /**
     * @brief 若处于错误状态则返回错误值，否则返回给定的默认错误。
     * @details
     * 语义与 value_or 对称，方便在“必须拿到一个 E”场景下使用。
     * @tparam U 可转换为 E 的类型。
     * @param u 默认错误。
     * @return 错误时错误值，否则 static_cast<E>(u)。
     */
    template <class U>
    constexpr E error_or(U && u) const &
    {
        return has_value() ? static_cast<E>(std::forward<U>(u)) : std::get<1>(st_).error();
    }

    /**
     * @brief 右值版本 error_or。
     */
    template <class U>
    constexpr E error_or(U && u) &&
    {
        return has_value() ? static_cast<E>(std::forward<U>(u))
                           : std::move(std::get<1>(st_)).error();
    }
    /*@}*/

    /*@{*/
    /**
     * @name Monadic 操作
     * @details
     * 所有 monadic 操作均保持错误类型 E 不变，确保错误语义在链式调用中不丢失。
     * and_then / or_else 要求返回类型必须为 expected<X,E>，防止跨错误域静默转换。
     * transform / transform_error 则分别对值或错误进行映射，允许改变值类型或错误类型。
     */
    /**
     * @brief 链式继续：若成功则调用 f，否则透传当前错误。
     * @details
     * and_then 要求 f 返回 expected<U,E>，从而允许继续链式组合。
     * 若当前为错误，则直接返回 Ret(unexpected_t<E>(error()))，不调用 f。
     * @tparam F 可调用对象，签名应为 expected<U,E>(T&) 或兼容形式。
     * @tparam Ret 自动推导为 F 的返回类型，必须满足 is_expected_with_error<Ret,E>。
     * @param f 延续函数。
     * @return 若成功则为 f 的结果，否则为 Ret(unexpected(error()))。
     */
    template <class F,
              class Ret = decltype(std::declval<F &>()(std::declval<T &>())),
              typename = std::enable_if_t<is_expected_with_error<Ret, E>::value>>
    auto and_then(F && f) & -> Ret
    {
        if (has_value())
            return f(std::get<0>(st_));
        return Ret(unexpected_t<E>(error()));
    }

    /**
     * @brief const 左值版本 and_then。
     */
    template <class F,
              class Ret = decltype(std::declval<F &>()(std::declval<const T &>())),
              typename = std::enable_if_t<is_expected_with_error<Ret, E>::value>>
    auto and_then(F && f) const & -> Ret
    {
        if (has_value())
            return f(std::get<0>(st_));
        return Ret(unexpected_t<E>(error()));
    }

    /**
     * @brief 右值版本 and_then。
     * @details
     * 当 *this 为成功时，将值 move 给 f；错误时亦将错误 move 至返回的 Ret。
     */
    template <class F,
              class Ret = decltype(std::declval<F &>()(std::declval<T &&>())),
              typename = std::enable_if_t<is_expected_with_error<Ret, E>::value>>
    auto and_then(F && f) && -> Ret
    {
        if (has_value())
            return f(std::move(std::get<0>(st_)));
        return Ret(unexpected_t<E>(std::move(*this).error()));
    }

    /**
     * @brief 值映射：若成功则调用 f 并包装其返回，否则透传错误。
     * @details
     * transform 允许将 T 映射为任意 U，但保持错误类型 E 不变。
     * 当 f 返回 expected 类型时，SFINAE 会排除本重载，防止与 and_then 冲突。
     * @tparam F 可调用对象，签名应为 U(T&) 或兼容形式。
     * @tparam U 自动推导的返回值类型，必须不是 expected 模板实例。
     * @param f 映射函数。
     * @return 若成功则为 expected<U,E>(f(value))，否则为 expected<U,E>(unexpected(error()))。
     */
    template <class F,
              class U = decltype(std::declval<F &>()(std::declval<T &>())),
              typename = std::enable_if_t<!is_expected_template<U>::value>>
    auto transform(F && f) & -> expected<U, E>
    {
        if (has_value())
            return expected<U, E>(f(std::get<0>(st_)));
        return expected<U, E>(unexpected_t<E>(error()));
    }

    /**
     * @brief const 左值版本 transform。
     */
    template <class F,
              class U = decltype(std::declval<F &>()(std::declval<const T &>())),
              typename = std::enable_if_t<!is_expected_template<U>::value>>
    auto transform(F && f) const & -> expected<U, E>
    {
        if (has_value())
            return expected<U, E>(f(std::get<0>(st_)));
        return expected<U, E>(unexpected_t<E>(error()));
    }

    /**
     * @brief 右值版本 transform。
     */
    template <class F,
              class U = decltype(std::declval<F &>()(std::declval<T &&>())),
              typename = std::enable_if_t<!is_expected_template<U>::value>>
    auto transform(F && f) && -> expected<U, E>
    {
        if (has_value())
            return expected<U, E>(f(std::move(std::get<0>(st_))));
        return expected<U, E>(unexpected_t<E>(std::move(*this).error()));
    }

    /**
     * @brief 错误映射：若失败则调用 g 并包装其返回，否则透传值。
     * @details
     * transform_error 与 transform 对称，允许将 E 映射为任意 E2，从而改变错误类型。
     * 成功时直接构造 expected<T,E2>(value)，失败时则构造 expected<T,E2>(unexpected(g(error())))。
     * @tparam G 可调用对象，签名应为 E2(E&) 或兼容形式。
     * @tparam E2 自动推导的新错误类型，必须不是 expected 模板实例。
     * @param g 错误映射函数。
     * @return 若成功则为 expected<T,E2>(value)，否则为 expected<T,E2>(unexpected(g(error())))。
     */
    template <class G,
              class E2 = decltype(std::declval<G &>()(std::declval<E &>())),
              typename = std::enable_if_t<!is_expected_template<E2>::value>>
    auto transform_error(G && g) & -> expected<T, E2>
    {
        using EE2 = E2;
        if (has_value())
            return expected<T, EE2>(std::get<0>(st_));
        return expected<T, EE2>(unexpected_t<EE2>(g(error())));
    }

    /**
     * @brief const 左值版本 transform_error。
     */
    template <class G,
              class E2 = decltype(std::declval<G &>()(std::declval<const E &>())),
              typename = std::enable_if_t<!is_expected_template<E2>::value>>
    auto transform_error(G && g) const & -> expected<T, E2>
    {
        using EE2 = E2;
        if (has_value())
            return expected<T, EE2>(std::get<0>(st_));
        return expected<T, EE2>(unexpected_t<EE2>(g(std::get<1>(st_).error())));
    }

    /**
     * @brief 右值版本 transform_error。
     */
    template <class G,
              class E2 = decltype(std::declval<G &>()(std::declval<E &&>())),
              typename = std::enable_if_t<!is_expected_template<E2>::value>>
    auto transform_error(G && g) && -> expected<T, E2>
    {
        using EE2 = E2;
        if (has_value())
            return expected<T, EE2>(std::move(std::get<0>(st_)));
        return expected<T, EE2>(unexpected_t<EE2>(g(std::move(std::get<1>(st_)).error())));
    }

    /**
     * @brief 错误恢复：若失败则调用 g，否则透传当前值。
     * @details
     * or_else 与 and_then 对称，要求 g 返回 expected<T,E>，从而允许在错误路径上执行恢复逻辑。
     * 若当前为成功，则直接返回 *this 的拷贝/移动；否则将错误传递给 g，由其决定如何恢复。
     * @tparam G 可调用对象，签名应为 expected<T,E>(E&) 或兼容形式。
     * @tparam Ret 自动推导为 g 的返回类型，必须满足 is_expected_with_error<Ret,E>。
     * @param g 恢复函数。
     * @return 若成功则为 *this 的拷贝/移动，否则为 g(error())。
     */
    template <class G,
              class Ret = decltype(std::declval<G &>()(std::declval<E &>())),
              typename = std::enable_if_t<is_expected_with_error<Ret, E>::value>>
    auto or_else(G && g) & -> Ret
    {
        using RR = Ret;
        if (has_value())
            return RR(std::get<0>(st_));
        return g(error());
    }

    /**
     * @brief const 左值版本 or_else。
     */
    template <class G,
              class Ret = decltype(std::declval<G &>()(std::declval<const E &>())),
              typename = std::enable_if_t<is_expected_with_error<Ret, E>::value>>
    auto or_else(G && g) const & -> Ret
    {
        using RR = Ret;
        if (has_value())
            return RR(std::get<0>(st_));
        return g(std::get<1>(st_).error());
    }

    /**
     * @brief 右值版本 or_else。
     */
    template <class G,
              class Ret = decltype(std::declval<G &>()(std::declval<E &&>())),
              typename = std::enable_if_t<is_expected_with_error<Ret, E>::value>>
    auto or_else(G && g) && -> Ret
    {
        using RR = Ret;
        if (has_value())
            return RR(std::move(std::get<0>(st_)));
        return g(std::move(std::get<1>(st_)).error());
    }
    /*@}*/

    /*@{*/
    /**
     * @name 交换
     */
    /**
     * @brief 成员 swap。
     * @details
     * 直接调用 storage_t::swap，异常规格与 std::variant 的 swap 保持一致。
     * 当 T 与 E 的 swap 均为 noexcept 时，整个操作为 noexcept。
     */
    void swap(expected & other) noexcept(std::is_nothrow_swappable<storage_t>::value)
    {
        st_.swap(other.st_);
    }
    /*@}*/

private:
    storage_t st_; ///< 内部存储，variant 的 discriminant 同时表示状态。
};

/**
 * @brief ADL 友好的自由函数 swap。
 * @details
 * 仅当 expected<T,E> 提供成员 swap 时启用，与 std::swap 形成重载决议，
 * 允许用户通过 using std::swap; swap(a,b); 的惯用法进行无异常交换。
 */
template <class T, class E>
void
swap(expected<T, E> & a, expected<T, E> & b) noexcept(noexcept(a.swap(b)))
{
    a.swap(b);
}
/**
 * @brief C++17 环境下对 C++23 std::expected<void,E> 的特化实现。
 *
 * 设计初衷：
 * 1. 与主模板 kp::expected<T,E> 形成互补，覆盖“仅关心成败、不携带返回值”的异步/事务场景。
 * 2. 空间最优：内部以 std::variant<char, unexpected_t<E>> 存储，char 仅作占位，
 *    保证 sizeof(expected<void,E>) == sizeof(unexpected_t<E>) + 1，与手写 union 等价。
 * 3. 接口一致性：保留 has_value / value() / error() / monadic 操作，使泛型代码无需区分 T=void
 * 特化。
 * 4. 异常安全：value() 在失败时抛出 bad_expected_access<E>，提供强异常保证。
 * 5. 可组合性：and_then / transform / or_else 等链式调用风格与主模板保持一致，
 *    方便编写“先执行 A 再执行 B”的连贯错误处理流程。
 *
 * 使用示例：
 * @code
 * kp::expected<void, std::string> tx() noexcept {
 *     if (!begin()) return kp::unexpected("begin failed");
 *     return {};
 * }
 *
 * auto r = tx().and_then([]()->kp::expected<void,std::string>{
 *     if (!commit()) return kp::unexpected("commit failed");
 *     return {};
 * });
 * @endcode
 *
 * @tparam E 错误类型，通常选用 std::error_code、std::string 或自定义错误枚举。
 */
template <class E>
class [[nodiscard]] expected<void, E>
{
    /**
     * @brief 内部存储类型。
     * @details
     * 0 号索引为 char，仅作“成功”占位，避免空 std::variant 的特例；<br>
     * 1 号索引为 unexpected_t<E>，表示“错误”状态。<br>
     * 借助 std::variant 的自动判别式，实现零额外空间开销。
     */
    using storage_t = std::variant<char, unexpected_t<E>>;

public:
    /*@{*/
    /**
     * @name 构造与赋值
     */
    /**
     * @brief 默认构造，进入“成功”状态。
     * @details
     * 与主模板语义保持一致：默认构造即成功，方便泛型代码统一书写。
     * @note noexcept 强保证，因为 char 的构造永不抛异常。
     */
    constexpr expected() noexcept : st_(char{}) {}

    /**
     * @brief 从 unexpected_t<E> 拷贝构造，进入“错误”状态。
     * @param ue 将被拷贝的错误包装对象
     */
    constexpr expected(unexpected_t<E> ue) : st_(std::move(ue)) {}

    /**
     * @brief 就地构造错误值。
     * @details
     * 使用 kp::unexpect 标签消除与默认构造的歧义，语义清晰。
     * @param e 将被移动存储的错误值
     */
    constexpr explicit expected(unexpect_t, E e) : st_(unexpected_t<E>(std::move(e))) {}
    /*@}*/

    /*@{*/
    /**
     * @name 状态查询
     */
    /**
     * @brief 查询是否处于“成功”状态。
     * @return 当且仅当内部持有 char 占位符时返回 true。
     * @note noexcept 且 constexpr，可放心在核心路径使用。
     */
    constexpr bool has_value() const noexcept { return std::holds_alternative<char>(st_); }

    /**
     * @brief 布尔转换，等价于 has_value()。
     * @details
     * 显式转换避免与整数类型的隐式比较，但允许在 if / while 等语境中直接使用。
     */
    constexpr explicit operator bool() const noexcept { return has_value(); }
    /*@}*/

    /*@{*/
    /**
     * @name 值访问
     * @details
     * 对于 void 特化，value() 不返回任何数据，仅作“成功”断言。
     */
    /**
     * @brief 成功断言。
     * @throw bad_expected_access<E> 若当前为错误状态。
     * @note 无返回值，与 std::expected<void,E> 保持一致。
     */
    void value() const
    {
        if (!has_value())
            throw bad_expected_access<E>(std::get<1>(st_).error());
    }
    /*@}*/

    /*@{*/
    /**
     * @name 错误访问
     * @pre has_value() == false，否则行为未定义（与 std::expected 保持一致）。
     */
    /**
     * @brief 左值引用访问错误值。
     * @return 内部 unexpected_t<E> 所持有的 E 的左值引用。
     */
    constexpr E & error() & { return std::get<1>(st_).error(); }

    /**
     * @brief const 左值引用访问错误值。
     * @return 内部 unexpected_t<E> 所持有的 E 的 const 左值引用。
     */
    constexpr const E & error() const & { return std::get<1>(st_).error(); }

    /**
     * @brief 右值引用访问错误值。
     * @return 内部 unexpected_t<E> 所持有的 E 的右值引用，支持移动语义。
     */
    constexpr E && error() && { return std::move(std::get<1>(st_)).error(); }
    /*@}*/

    /*@{*/
    /**
     * @name 就地重新构造
     */
    /**
     * @brief 就地置为“成功”状态。
     * @details
     * 无论原状态如何，均覆盖为 char 占位符，表示成功。
     */
    void emplace() { st_.template emplace<0>(char{}); }

    /**
     * @brief 就地构造错误值，覆盖当前状态。
     * @details
     * 内部通过 unexpected_t<E>(E(...)) 包装，保证与构造函数的语义一致性。
     * @tparam Args 传递给 E 构造函数的形参包。
     * @return 新构造的 E 的左值引用。
     */
    template <class... Args>
    E & emplace_error(Args &&... args)
    {
        st_.template emplace<1>(unexpected_t<E>(E(std::forward<Args>(args)...)));
        return std::get<1>(st_).error();
    }
    /*@}*/

    /*@{*/
    /**
     * @name Monadic 操作
     * @details
     * 所有 monadic 操作均保持错误类型 E 不变，确保错误语义在链式调用中不丢失。
     * and_then / or_else 要求返回类型必须为 expected<X,E>，防止跨错误域静默转换。
     * transform / transform_error 则分别对“成功”或“错误”进行映射，允许改变值类型或错误类型。
     */
    /**
     * @brief 链式继续：若成功则调用 f，否则透传当前错误。
     * @details
     * and_then 要求 f 返回 expected<U,E>，从而允许继续链式组合。
     * 若当前为错误，则直接返回 Ret(unexpected_t<E>(error()))，不调用 f。
     * @tparam F 可调用对象，签名应为 expected<U,E>() 或兼容形式。
     * @tparam Ret 自动推导为 F 的返回类型，必须满足 is_expected_with_error<Ret,E>。
     * @param f 延续函数。
     * @return 若成功则为 f 的结果，否则为 Ret(unexpected(error()))。
     */
    template <class F,
              class Ret = decltype(std::declval<F &>()()),
              typename = std::enable_if_t<is_expected_with_error<Ret, E>::value>>
    auto and_then(F && f) & -> Ret
    {
        if (has_value())
            return f();
        return Ret(unexpected(error()));
    }

    /**
     * @brief const 左值版本 and_then。
     */
    template <class F,
              class Ret = decltype(std::declval<F &>()()),
              typename = std::enable_if_t<is_expected_with_error<Ret, E>::value>>
    auto and_then(F && f) const & -> Ret
    {
        if (has_value())
            return f();
        return Ret(unexpected(std::get<1>(st_).error()));
    }

    /**
     * @brief 右值版本 and_then。
     * @details
     * 当 *this 为成功时，直接调用 f；错误时亦将错误 move 至返回的 Ret。
     */
    template <class F,
              class Ret = decltype(std::declval<F &>()()),
              typename = std::enable_if_t<is_expected_with_error<Ret, E>::value>>
    auto and_then(F && f) && -> Ret
    {
        if (has_value())
            return f();
        return Ret(unexpected(std::move(std::get<1>(st_)).error()));
    }

    /**
     * @brief 值映射：若成功则调用 f 并包装其返回，否则透传错误。
     * @details
     * transform 允许将 void 成功映射为任意 U，但保持错误类型 E 不变。
     * 当 f 返回 expected 类型时，SFINAE 会排除本重载，确保语义清晰。
     * @tparam F 可调用对象，签名应为 U() 或兼容形式。
     * @tparam U 自动推导为 F 的返回类型，且不得为 expected 模板实例。
     * @param f 映射函数。
     * @return 若成功则为 expected<U,E>(f())，否则为 expected<U,E>(unexpected(error()))。
     */
    template <class F,
              class U = decltype(std::declval<F &>()()),
              typename = std::enable_if_t<!is_expected_template<U>::value>>
    auto transform(F && f) & -> expected<U, E>
    {
        if (has_value())
            return expected<U, E>(f());
        return expected<U, E>(unexpected_t<E>(error()));
    }

    /**
     * @brief const 左值版本 transform。
     */
    template <class F,
              class U = decltype(std::declval<F &>()()),
              typename = std::enable_if_t<!is_expected_template<U>::value>>
    auto transform(F && f) const & -> expected<U, E>
    {
        if (has_value())
            return expected<U, E>(f());
        return expected<U, E>(unexpected_t<E>(std::get<1>(st_).error()));
    }

    /**
     * @brief 右值版本 transform。
     */
    template <class F,
              class U = decltype(std::declval<F &>()()),
              typename = std::enable_if_t<!is_expected_template<U>::value>>
    auto transform(F && f) && -> expected<U, E>
    {
        if (has_value())
            return expected<U, E>(f());
        return expected<U, E>(unexpected_t<E>(std::move(std::get<1>(st_)).error()));
    }

    /**
     * @brief 错误映射：若失败则调用 g 并包装其返回，否则透传成功。
     * @details
     * transform_error 允许将 E 映射为任意 E2，且成功状态保持不变。
     * @tparam G 可调用对象，签名应为 E2(E&) 或兼容形式。
     * @tparam E2 自动推导为 G 的返回类型，且不得为 expected 模板实例。
     * @param g 错误映射函数。
     * @return 若失败则为 expected<void,E2>(unexpected(g(error())))，否则为 expected<void,E2>()。
     */
    template <class G,
              class E2 = decltype(std::declval<G &>()(std::declval<E &>())),
              typename = std::enable_if_t<!is_expected_template<E2>::value>>
    auto transform_error(G && g) & -> expected<void, E2>
    {
        using EE2 = E2;
        if (has_value())
            return expected<void, EE2>();
        return expected<void, EE2>(unexpected_t<EE2>(g(error())));
    }

    /**
     * @brief const 左值版本 transform_error。
     */
    template <class G,
              class E2 = decltype(std::declval<G &>()(std::declval<const E &>())),
              typename = std::enable_if_t<!is_expected_template<E2>::value>>
    auto transform_error(G && g) const & -> expected<void, E2>
    {
        using EE2 = E2;
        if (has_value())
            return expected<void, EE2>();
        return expected<void, EE2>(unexpected_t<EE2>(g(std::get<1>(st_).error())));
    }

    /**
     * @brief 右值版本 transform_error。
     */
    template <class G,
              class E2 = decltype(std::declval<G &>()(std::declval<E &&>())),
              typename = std::enable_if_t<!is_expected_template<E2>::value>>
    auto transform_error(G && g) && -> expected<void, E2>
    {
        using EE2 = E2;
        if (has_value())
            return expected<void, EE2>();
        return expected<void, EE2>(unexpected_t<EE2>(g(std::move(std::get<1>(st_)).error())));
    }

    /**
     * @brief 错误处理：若失败则调用 g，否则透传成功。
     * @details
     * or_else 要求 g 返回 expected<void,E>，从而允许在失败时进行“补救”或“包装”。
     * 若当前为成功，则直接返回 expected<void,E>()，不调用 g。
     * @tparam G 可调用对象，签名应为 expected<void,E>(E&) 或兼容形式。
     * @tparam Ret 自动推导为 G 的返回类型，必须满足 is_expected_with_error<Ret,E>。
     * @param g 错误处理函数。
     * @return 若失败则为 g 的结果，否则为 expected<void,E>()。
     */
    template <class G,
              class Ret = decltype(std::declval<G &>()()),
              typename = std::enable_if_t<is_expected_with_error<Ret, E>::value>>
    auto or_else(G && g) & -> Ret
    {
        using RR = Ret;
        if (has_value())
            return RR();
        return g(error());
    }

    /**
     * @brief const 左值版本 or_else。
     */
    template <class G,
              class Ret = decltype(std::declval<G &>()()),
              typename = std::enable_if_t<is_expected_with_error<Ret, E>::value>>
    auto or_else(G && g) const & -> Ret
    {
        using RR = Ret;
        if (has_value())
            return RR();
        return g(std::get<1>(st_).error());
    }

    /**
     * @brief 右值版本 or_else。
     */
    template <class G,
              class Ret = decltype(std::declval<G &>()()),
              typename = std::enable_if_t<is_expected_with_error<Ret, E>::value>>
    auto or_else(G && g) && -> Ret
    {
        using RR = Ret;
        if (has_value())
            return RR();
        return g(std::move(std::get<1>(st_)).error());
    }
    /*@}*/

    /*@{*/
    /**
     * @name 默认值策略
     */
    /**
     * @brief 若处于错误状态则返回错误值，否则返回给定的默认错误。
     * @details
     * 语义与主模板的 error_or 保持一致，方便在“必须拿到一个 E”场景下使用。
     * @tparam U 可转换为 E 的类型。
     * @param u 默认错误。
     * @return 错误时错误值，否则 static_cast<E>(u)。
     */
    template <class U>
    constexpr E error_or(U && u) const
    {
        return has_value() ? static_cast<E>(std::forward<U>(u)) : std::get<1>(st_).error();
    }
    /*@}*/

private:
    storage_t st_; ///< 实际存储的 variant，成功时为 char，错误时为 unexpected_t<E>
};

} // namespace kp
#else

#include <expected>
namespace kp
{

template <class T, class E>
using expected = std::expected<T, E>;

template <class E>
using unexpected_t = std::unexpected<E>;

template <class E>
inline std::unexpected<E>
unexpected(E e)
{
    return std::unexpected<E>(std::move(e));
}

using unexpect_t = std::unexpect_t;
inline constexpr std::unexpect_t unexpect{};

template <class E>
using bad_expected_access = std::bad_expected_access<E>;

} // namespace kp
#endif
